package com.pandora.common.check;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import com.pandora.common.exception.EduException;
import com.pandora.common.util.CommonUtils;
import com.pandora.common.util.FileUtils;
import com.pandora.common.util.MD5Utils;
import com.pandora.common.util.StringUtils;
import com.pandora.common.util.VerifyUtils;
import com.pandora.common.util.WebUtils;
import com.pandora.framework.constant.ResponseConstants;
import com.pandora.framework.constant.ServiceConstants;
import com.pandora.framework.util.LogUtils;
import com.pandora.framework.vo.ServiceCoreVO;

/**
 * 请求体校验
 * 
 * @author JingChenglong 2017/12/20 14:55
 *
 */
public class RequestChecks {

	private ServiceCoreVO serviceCoreVO = null;
	private HttpServletRequest request = null;

	public RequestChecks() {
	}

	public RequestChecks(ServiceCoreVO serviceCoreVO, HttpServletRequest request) {
		this.serviceCoreVO = serviceCoreVO;
		this.request = request;
	}

	public static RequestChecks getInstance(ServiceCoreVO serviceCoreVO, HttpServletRequest request) {
		return new RequestChecks(serviceCoreVO, request);
	}

	/**
	 * 校验请求体信息
	 * 
	 * @return
	 * @throws EduException
	 */
	public ServiceCoreVO checkRequest() throws EduException {

		checkAction();
		checkFormat();
		checkMethod();
		checkReqLengh();
		checkSign();
		checkContentLength();
		setReqcontentEncrypt();

		return serviceCoreVO;
	}

	/** 校验请求action */
	private void checkAction() throws EduException {

		String action = WebUtils.getHeaderDecode(request, ServiceConstants.ACTION).toLowerCase();

		if (StringUtils.isEmpty(action)) {
			return;
		}

		ConfigChecks.checkAction(action);
		serviceCoreVO.setAction(action);
	}

	/** 校验数据格式 */
	private void checkFormat() throws EduException {

		String format = WebUtils.getHeaderDecode(request, ServiceConstants.FORMAT).toLowerCase();
		if (ServiceConstants.JSON.equals(StringUtils.nullToStrTrim(format))) {
			serviceCoreVO.setFormat(ServiceConstants.JSON);
		} else {
			serviceCoreVO.setFormat(ServiceConstants.XML);
		}
	}

	/** 校验请求方法类型 */
	private void checkMethod() throws EduException {

		String requestMethod = StringUtils.nullToStrTrim(request.getMethod());
		if (!ServiceConstants.REQUEST_METHOD_POST.equalsIgnoreCase(requestMethod)) {
			throw new EduException(ResponseConstants.REQUEST_METHOD_NOSUPPORT);
		}
	}

	/** 校验请求体长度 */
	private void checkReqLengh() throws EduException {

		String reqLength = StringUtils.nullToStrTrim(WebUtils.getHeader(request, ServiceConstants.REQLENGTH));
		if (StringUtils.isEmpty(reqLength)) {
			throw new EduException(ResponseConstants.REQLENGTH_ISNULL);
		}

		if (reqLength.length() > 10 || !VerifyUtils.checkString(reqLength, VerifyUtils.MATCH_NUMBER)) {
			throw new EduException(ResponseConstants.REQLENGTH_FORMAT_FAIL);
		}

		int reqLengthI = StringUtils.nullToIntZero(reqLength);
		if (reqLengthI == 0) {
			throw new EduException(ResponseConstants.REQLENGTH_ISNULL);
		}

		int maxLength = StringUtils.isEmpty(serviceCoreVO.getAction()) ? ServiceConstants.CONTENT_LENGTH
				: ServiceConstants.CONTENT_LENGTH_MAX;

		if (reqLengthI > maxLength) {
			throw new EduException(ResponseConstants.REQUEST_ENTITY_TOOLARGE);
		}

		serviceCoreVO.setReqlength(reqLengthI);
	}

	/** 校验签名 */
	private void checkSign() throws EduException {

		String sign = StringUtils.nullToStrTrim(WebUtils.getHeaderDecode(request, ServiceConstants.SIGN));

		if (StringUtils.isEmpty(sign)) {
			throw new EduException(ResponseConstants.SIGN_IS_NULL);
		}
		if (!StringUtils.isHalfAngle(sign) || sign.length() > 80) {
			throw new EduException(ResponseConstants.SIGN_ERROR);
		}

		serviceCoreVO.setSign(sign);
	}

	/** 校验请求体内容长度 */
	private void checkContentLength() throws EduException {

		int contentLength = request.getContentLength();
		int maxLength = StringUtils.isEmpty(serviceCoreVO.getAction()) ? ServiceConstants.CONTENT_LENGTH
				: ServiceConstants.CONTENT_LENGTH_MAX;

		if (contentLength == 0 && StringUtils.isEmpty(serviceCoreVO.getAction())) {
			throw new EduException(ResponseConstants.REQUEST_CONTENT_ISEMPTY);
		}
		if (contentLength > maxLength) {
			throw new EduException(ResponseConstants.REQUEST_ENTITY_TOOLARGE);
		}
		if (contentLength != serviceCoreVO.getReqlength()) {
			throw new EduException(ResponseConstants.REQLENGTH_LENGTH_UNMATCH);
		}
	}

	/** 设置请求内容加密签名值 */
	private void setReqcontentEncrypt() throws EduException {

		String reqContentMD5 = "";

		if (StringUtils.isEmpty(serviceCoreVO.getAction())) {
			String reqContent = "";
			try {
				reqContent = FileUtils.generateContent(request.getInputStream());
			} catch (IOException e) {
				LogUtils.logError(CommonUtils.getTraceInfo() + e.getMessage());
				reqContent = "";
			}

			// 客户端中断时，reqContent会报null;
			if (StringUtils.isEmpty(reqContent)) {
				throw new EduException(ResponseConstants.REQUEST_CONTENT_GET_FAIL);
			}

			serviceCoreVO.setReqContent(reqContent);
			reqContentMD5 = MD5Utils.md5(reqContent).toLowerCase();
			if (StringUtils.isEmpty(reqContentMD5)) {
				throw new EduException(ResponseConstants.REQUEST_CONTENT_GET_FAIL);
			}
		} else {
			reqContentMD5 = WebUtils.getHeaderDecode(request, ServiceConstants.REQCONTENTMD5);
			if (StringUtils.isEmpty(reqContentMD5)) {
				throw new EduException(ResponseConstants.REQUEST_MD5_ISNULL);
			}
			if (!VerifyUtils.checkMD5(reqContentMD5)) {
				throw new EduException(ResponseConstants.REQUEST_MD5_FAIL);
			}
		}

		serviceCoreVO.setReqcontentmd5(reqContentMD5);
	}
}